#pragma once

#include "Vertex.h"

#include "Region.h"
#include "State.h"
#include "StateMachine.h"
#include "Transition.h"

namespace uml {

void Vertex::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    PartialElement::fromJson(json, errorList);
    container_ = JsonSerializable::create<Region>(json.value("container"), errorList);

    JsonSerializable::fromJsonArray(incomings_, "incomings", json, errorList);
    JsonSerializable::fromJsonArray(outgoings_, "outgoings", json, errorList);
}

void Vertex::toJson(QJsonObject& json) {
    PartialElement::toJson(json);
    if (container_) {
        QJsonObject container_json;
        container_->toJson(container_json);
        json.insert("container", container_json);
    }
    JsonSerializable::toJsonArray(incomings_, "incomings", json);
    JsonSerializable::toJsonArray(outgoings_, "outgoings", json);
}

/// <summary>
/// containingStateMachine
    /// The operation containingStateMachine() returns the StateMachine in which this
    /// Vertex is defined.
/// </summary>
    /// <code>
    /// result = (if container <> null
    /// then
    /// -- the container is a region
    ///    container.containingStateMachine()
    /// else 
    ///    if (self.oclIsKindOf(Pseudostate)) and ((self.oclAsType(Pseudostate).kind = PseudostateKind::entryPoint) or (self.oclAsType(Pseudostate).kind = PseudostateKind::exitPoint)) then
    ///       self.oclAsType(Pseudostate).stateMachine
    ///    else 
    ///       if (self.oclIsKindOf(ConnectionPointReference)) then
    ///           self.oclAsType(ConnectionPointReference).state.containingStateMachine() -- no other valid cases possible
    ///       else 
    ///           null
    ///       endif
    ///    endif
    /// endif
    /// 
    /// )
    /// </code>
shared_ptr<StateMachine> Vertex::containingStateMachine() const
{
    return nullptr;
}

/// <summary>
/// isContainedInState
    /// This utility operation returns true if the Vertex is contained in the State s
    /// (input argument).
/// </summary>
    /// <code>
    /// result = (if not s.isComposite() or container->isEmpty() then
    /// 	false
    /// else
    /// 	if container.state = s then 
    /// 		true
    /// 	else
    /// 		container.state.isContainedInState(s)
    /// 	endif
    /// endif)
    /// </code>
bool Vertex::isContainedInState(shared_ptr<State> s) const
{
    return false;
}

/// <summary>
/// isContainedInRegion
    /// This utility query returns true if the Vertex is contained in the Region r
    /// (input argument).
/// </summary>
    /// <code>
    /// result = (if (container = r) then
    /// 	true
    /// else
    /// 	if (r.state->isEmpty()) then
    /// 		false
    /// 	else
    /// 		container.state.isContainedInRegion(r)
    /// 	endif
    /// endif)
    /// </code>
bool Vertex::isContainedInRegion(shared_ptr<Region> r) const
{
    return false;
}

/// <summary>
/// container getter
/// The Region that contains this Vertex.
/// </summary>
shared_ptr<Region> Vertex::container() const {
    return container_;
}

/// <summary>
/// container setter
/// The Region that contains this Vertex.
/// </summary>
void Vertex::setContainer(shared_ptr<Region> value) {
    container_ = value;
}

/// <summary>
/// incomings getter
/// Specifies the Transitions entering this Vertex.
/// </summary>
vector<shared_ptr<Transition>>& Vertex::incomings() {
    return incomings_;
}

/// <summary>
/// outgoings getter
/// Specifies the Transitions departing from this Vertex.
/// </summary>
vector<shared_ptr<Transition>>& Vertex::outgoings() {
    return outgoings_;
}

} // namespace uml
